Ext.define('TS.lib.Factory',{
	Counter:function Counter(max,cb){
		this.cb = cb || Ext.emptyFn;
        this.max = max || 10000;
        this.count = 0;
		this.tik = function(){
			this.count++;
			if(this.count == this.max){
				this.cb();
			}
		};
	},
	confirm : function(title,msg,fn){ // TODO ?? czy to utils
	    Ext.Msg.confirm(
	        title || 'Potwierdzenie',msg,
	        function(e){
	            if (e == 'yes'){
	            	fn();
	            }
	        }
	    );
	},
	rend: {
		div:function(v,x,s){
			return '<div style="white-space:normal;padding:10px;">'+v+'<div/>';
		},
		date:function(v,x,s){
			
			if(Ext.isDate(v)){
				return (v.getFullYear()== -1) ? null : Ext.Date.format(v,'Y-m-d');
			} else {
				return v;
			}
		},
		dict:function(dict){
			//stack(arguments);
			return function(v,x,s){
				if (v && v != ''){
					var i = dict.queryBy(function(r){
						return r.data && (r.data.id == v);
					});
					return (i && i.items && i.items.length > 0) ? i.getAt(0).data.name : v;
				}
			};
		},
		loose_dict: function(v,dict,def){
			if (v && v != ''){
				try {
					return dict.queryBy(function(r){return r.data.id == v;}).getAt(0).data.name;
				} catch (e){return v;}
			}
			return def;
		},
		multidict: function(dict){
			return function(v,x,s){
				var out = '<div style="white-space:normal;">';
				if(typeof v.split ==='function')
					v = v.split(',');
				
				for(var i = 0 ; i<v.length;i++){
					out+=Factory.rend.loose_dict(v[i],dict,'-');
					if((i+1)<v.length)out+=', ';//', <br/>'
				}
				return out+'</div>';
			}
		},
		icon:function(C){
			return function(v,x,s){
				return Ext.String.format(HTML.icon,
					C.fn, v,null, C.img, C.label || ''
				);
			};
		},
		percent : function(v){
			return (parseFloat(v) * 100).toFixed(2)+'%';
		},
		money : function(v,x,s){
			if(v || v===0){
				var str = (typeof v.toFixed === 'function') ? 
					v.toFixed(0) :	v.indexOf('.')>=0 ? v.substring(0,v.indexOf('.')) : v;
				
				var str_arr = [];
				while (str.length>=3){
				  str_arr.unshift(str.substr(str.length-3,3));
				  str = str.substring(0,str.length-3);
				}
				str_arr.unshift(str);// dodaje końcówkę - 1-2 pierwsze cyfry
				
				(USER.currency && USER.currency.show) && str_arr.push(USER.currency.label);// dodaje walutę
				
				return str_arr.join(' ');
			}
		},
		yearMonth:function(v){// używany też do wstawienia wartosi do pól formularza stad test "this.dataIndex" - do forma niewstawimy -
			return (!v || isIn(v,'1902-01-01','2037-01-01')) ? (this.dataIndex ? '-' : null ) : v.substr(0,7);
		},
		stringToDate:function(v){
			return isIn(v,'0000-00-00 00:00:00','0000-00-00') ? '-' :
				Ext.Date.format(Ext.Date.parseDate(v,'c'),CONST.format.date);
		}
	},
	dict:{
		blah:function(){
			return Ext.create('TS.lib.dict.Array',{data:[
					[1,'jeden'],[2,'dwa'],[3,'trzy']
			]});
		},
		array:function(){
			var data = Array.prototype.slice.call(arguments); 
			return Ext.create('TS.lib.dict.Array',{data:data}); 
		},
		good:function(c){
			if(Ext.isString(c))c={name:c};
			
			return Ext.create('TS.lib.dict.Normal',{
				proxy:Factory.proxy(URL.util.dict,'id',c)
			});
		}
	},
	proxy : function(url,idProperty,extraParams){
		return {
			url:url,
			type: 'ajax',
			extraParams:extraParams,
			simpleSortMode : true,
			reader: {
				type: 'json',
				root: 'rows',
				totalProperty:'total',
				successProperty: 'success',
				idProperty:idProperty || 'id'
			}
		};
	},
	toolbar:{
		_:{
			go:function(btnOrStoreName,flds,fix,isExport){
				var b = btnOrStoreName;
				
				if(Ext.isString(b)){// jesli używane jako standAlone a nie handler
					var s = b;
				} else {
					var s = b.up('grid').getStore();
					flds = b.flds;
					fix = b.fix;
					isExport = b.isExport;
				}
				
				fix = fix ? fix+'->' : '';
				var wheres = [];
				for(x in flds){
					for(i=0;i<flds[x].length;i++){
						Factory.toolbar._.where[x](fix+flds[x][i],wheres);	
					}
				}
				if(isExport){
					var where = multiWhere(wheres);
					var p = wheres.length>0 ? {where:where.replace(/\"/g,"'")} : null;// TODO przerobi download form !!!
					//var p = wheres.length>0 ? {where:where} : null;
					Util.download(b.urlAction,p);
				} else {
					Util.s.load(s, wheres.length>0 && multiWhere(wheres));
				}
			},
			where:{
				hidden:function(name,wheres){
					var t = name.indexOf('->')>0,
						contName = t ? name.split('->')[0] : 'viewport',
						fldName = t ? name.split('->')[1] : name;
					
					var fld = Util.cmp(contName+' hidden[name='+fldName+']'),
						val = fld.getVal()
						fld_wheres = [];
					
					if(Ext.isArray(fld.names)){
						for(var i=0;i<fld.names.length;i++){
							var f = fld.names[i];
							fld_wheres.push([f,val,'=',fld_wheres.length>0?'OR':null])
						}
						if(fld_wheres.length>0){
							wheres.push({parts:fld_wheres,operator:wheres.length>0?'AND':null})
						}
					}
						
				},
				text:function(name,wheres){
					var t = name.indexOf('->')>0,
						contName = t ? name.split('->')[0] : 'viewport',
						fldName = t ? name.split('->')[1] : name;
						
					var fld = Util.cmp(contName+' text[name='+fldName+']'),
						v = fld.getValue();
					v && wheres.push([fld.dbName || fldName,v+'%','LIKE']);
				},
				multi:function(name,wheres){
					var t = name.indexOf('->')>0,
						contName = t ? name.split('->')[0] : 'viewport',
						fldName = t ? name.split('->')[1] : name;
						
					var fld = Util.cmp(contName+' combo[name='+fldName+']'),
						values = fld.getValue(),
						fld_wheres = [];
					if(Ext.isArray(values)){// pusty nie jest arrayem (a przynajmniej wyczyszczony)
						for(var i=0;i<values.length;i++){
							var v = values[i];
							if(v){// nie jest pusty (wszystkie)
								fld_wheres.push([fld.dbName || fldName,v,'=',fld_wheres.length>0?'OR':null])
							} else {
								fld_wheres=[];
								i=values.length;
							}
						}
						if(fld_wheres.length>0){
							wheres.push({parts:fld_wheres,operator:wheres.length>0?'AND':null})
						}
					}
				},
				date: function(name,wheres){
					var t = name.indexOf('->')>0,
						contName = t ? name.split('->')[0] : 'viewport',
						fldName = t ? name.split('->')[1] : name;
					
					//USAGE : this.util.produce.date('order_modified','>=',wheres);					
					var fld = Util.cmp(contName+' date[name='+fldName+']'),
						val = fld.getValue(); 
					val && wheres.push([fld.dbName || fldName,val,fld.sign || '=',wheres.length>0?'AND':null]);
				}
			}
		},
		pager:function(store,C){C=C||{};
		
			return Ext.create('Ext.PagingToolbar',{
		        id:C.id,
		        hidden:C.hide,
		        store:  Ext.data.StoreManager.lookup(store),
		        displayInfo:false,
		        style:{background:'white'},
		        hideMode:'display',
		        hideBorders:true,
		        enableOverflow:false,
		        hideLabel:true,
		        emptyMsg: 'Brak wyników do wyświetlenia'
		    });
			
		},
		search : function(itemsOrActive,addFldFn,prepare){
			if(Ext.isArray(itemsOrActive)){
				var flds = itemsOrActive;
				var items = [{
					action:'search',
					icon:URL.icon('search.png'),
					handler:function(){
						wheres=[];
						for(var i = 0 ; i<flds.length;i++){
							var f = flds[i];
							
							var item = this.nextSibling(f.xtype+'[name='+f.name+']'),
								v = typeof item.getValue === 'function' ? item.getValue() : null;
							
							is(v) && wheres.push([
								f.searchName || f.name,
								f.searchTpl? f.searchTpl.replace('{x}',v):v,
								f.searchSign||'=',
								wheres.length>0?'AND':undefined
							]);
						}
						try {
							if(addFldFn){
								var af = addFldFn(this);
								if(!Ext.isArray(af)){
									af = [af];
								}
								for(var j=0;j<af.length;j++){
									var v = af[j].value;
									
									if(!v||v=='')throw 'Nie okeślono parametru '+af[j].name;
									
									wheres.push([
										af[j].name,
										af[j].value,
										af[j].sign || '=',
										wheres.length>0?'AND':undefined
									])
								}
							}
							if(typeof prepare ==='function' && prepare()!==true){
								return;
							}
							Util.s.load(this.up('grid').store,wheres.length>0 ? moreWhere(wheres) : null);
							
						} catch (e){
							Factory.flyer.bad(e);
						}
					}
				}];	
				for(var i =0;i<flds.length;i++){
					items.push(flds[i]);	
				}
							
			} else {
				var has_active = itemsOrActive;
				var items = [{
					scale:'small',icon:URL.icon('search.png'),
					handler:function(){
						var s = this.up('grid').store;
						if(has_active == true || Ext.isString(has_active)){
							var v = this.nextSibling('combo[name=active]').getValue();
							s.setBaseParam('where',v!='' ? simpleWhere(Ext.isString(has_active)?has_active:'active',v) : false);
						}
						s.load();
					}
				}];
				
				if(has_active){
					items.push({xtype:'combo',
						width:80,name:'active',allowBlank:true,value:1,
						empty:'Aktywność',store:Dict.active_search
					});
				}
			}
			//return Ext.create('Ext.Toolbar',{autoDestroy:true,items:items});
			return items;
		},
		page :function(store){
			return {
		        xtype: 'pagingtoolbar',
		        store: store,   // same store GridPanel is using
		        dock: 'bottom',
		        displayInfo: true,
		        emptyMsg: 'Brak wyników do wyświetlenia'
		        
		    };
		}
	},
	tool: function(text,hand,id,qtip,width,tpl){// TODO rozszerzenie komponentu tool; + żeby sie nie rozjeżdzało !
		
		tpl = tpl || [
				'<div {qtip} class="my-tool">',
	        	'<div class="my-tool-right">&nbsp;</div>',
	        	'<div class="my-tool-bg" {id}>{text}</div>',
	        	'<div class="my-tool-left">&nbsp;</div>',
	        '</div>'
	    ];
		
		return {
			xtype:'component',
			minWidth:width || 55,
			renderData:{
				text:text,
				id:id? 'id="'+id+ '"' : '',
				qtip:qtip ? ' ext:qtip="'+qtip+'"' : ''
			},// TODO qtip ???
			listeners:{
				render:function(){
					this.getEl().on('click',hand,this);
				}
			},
			renderTpl:new Ext.XTemplate(tpl)
		};
	},
	layout: {
		column : function(){
			var fix = Ext.isNumeric(arguments[0]) ? 1 : 0;
			
			var count = arguments.length-fix,
				width = fix ? (1-arguments[0])/(count-1) : 1/count,
				cols = [];
			
			for (var i = fix; i<(count+fix);i++){
				cols.push(
					{border:false,layout:'anchor',columnWidth:fix && i == 1 ? arguments[0] : width,items:arguments[i]}
				);
			}
			
			return {layout:'column',border:false,style:{backgroundColor:'#99BCE8'},items:Ext.isArray(cols)?cols:[cols]};
		},
		duoTab:function(title,clazz,docked){
			return {
				title:title,
				docked:docked,
				xtype:clazz+'grid',
				//layout:'fit',
				rbar:[{
					xtype:clazz+'form',
					width:500
				}]
			}
		},
		borderTab:function(title,clazz,width){
			return {
				title:title,
				layout:'border',
				items:[{
					region:'center',
					xtype:clazz+'grid'
				},{
					region:'east',
					xtype:clazz+'form',
					width:width || 500
				}]
			};
		},
		borderDuo:function(title,clazz,cfg,formCfg){
			formCfg = formCfg||{};
			Ext.apply(formCfg,{region:'east',width:300,xtype:clazz+'form'});
			
			var winCfg = {
				layout:'border',width:600,height:300,
				title:title,
				items:[{region:'center',xtype:clazz+'grid'},formCfg]
			};
			!cfg || Ext.apply(winCfg,cfg);
			return winCfg;
			
		},
		fieldset:function(){
			var args = Array.prototype.slice.call(arguments);
			return {
				xtype:'fieldset',
				title:args.shift(),
				items:args
			};
		}
	},
	// TODO raczej do wywalenia - przerobienia na cos uniwersalnego w konwencji
	winForm:function(clazz,newTitle,typeOrCfg,formCfg){// TODO formCfg - na razie tylko pod scope stawek
		var type = typeOrCfg ? (Ext.isString(typeOrCfg) ? typeOrCfg : typeOrCfg.type) : null;
		
		switch (type){
			case 'single':
			case 'simple':
				formCfg = formCfg||{};
				Ext.apply(formCfg,{xtype:clazz+'form'});
				var cfg = {
					width:400,
					layout:'anchor',
					//height:300,
					title:newTitle,
					items:[formCfg]
				};
				break;
			case 'duo':
			default:
				var cfg = Factory.layout.borderDuo(newTitle,clazz,typeOrCfg,formCfg);
				break;
		}
		
		var f = Util.form(clazz);
		if (!f){
			var newWin = Ext.create('TS.lib.Window',cfg);
			newWin.toFront();
			
			f = Util.form(clazz);
		} else {
			var newWin = f.up('window')
			newWin.setTitle(newTitle);
			newWin.toFront();
			f.getForm().reset();
			!formCfg || Ext.apply(f,formCfg);
			f.fireEvent('render',f);
		}
		
		return f;
	},
	plugin:{
		dd:function(group,drag,drop){
			return {
				ptype:'gridviewdragdrop',
				dragText:'Przeciągnij obiekt',
				enableDrag:drag,
				enableDrop:drop,
				ddGroup:group
			};
		},
		edit : function(){
			//return Ext.create('Ext.grid.plugin.CellEditing', {// TODO przerobic na xtype ??
			return {ptype:'cellediting',
				pluginId:'edit',
			    clicksToEdit: 1//,listeners:{afteredit:My.hand.editorSalvator}
			//});
			};
		},
		grouping :function(dict){
			return Ext.create('Ext.grid.feature.Grouping', {
				groupHeaderTpl:'{[Factory.rend.loose_dict(values.name,'+dict+',values.name)]}',
				groupByText :'Grupuj po tym polu',
				showGroupsText:'Pokaż pogrupowane', 
				enableNoGroups:false,
				enableGroupingMenu:false,
			    startCollapsed: false // start all groups collapsed
			});
		}
	},
	flyer : {
		GEN : function(msg,type){
			
			var DEF = {
				width:300,
				corner: 'bl',// TODO było br - ale to tam gdzie formularze maja przyciski!
				cls: 'ux-notification-light',
				title: 'Timesheet 2.0',
				//manager:'whatever',
				slideInDelay: 500,
				slideDownDelay: 500,
				//spacing:20,
				stickOnClick: true,
				stickWhileHover: true,
				//useXAxis: true,//???
				
				slideInAnimation: 'elasticIn',// bounceOut, elasticIn
				slideDownAnimation: 'elasticIn'
			};
			
			if(type){
				if(type == 'info'){
					DEF.iconCls = 'ux-notification-icon-information';
					var color = 'blue';
				} else {
					DEF.iconCls = 'ux-notification-icon-error';
					var color = 'red';
				}
				DEF.closable = true;
				DEF.autoDestroy = false;// TODO true = same znikają;
				DEF.html = '<span style="color:'+color+';">'+msg+'</span>';
			} else {
				DEF.autoDestroyDelay = 2000;
				DEF.html = '<span style="color:green;">'+msg+'</span>';
			}
			
			var flyer = Ext.create('widget.uxNotification', DEF);
			flyer.show();
			flyer.getEl().on('mouseleave',function(){
				//flyer.fireEvent('beforehide',flyer);
				flyer.destroy();
			});
			
		},
		bad : function(msg){
			Factory.flyer.GEN(msg,'error');// TODO pomyslec nad istnieniem factory
		},
		good : function(msg){
			Factory.flyer.GEN(msg);
		},
		log : function(msg){
			Factory.flyer.GEN(msg,'info');
		}
	},
	btn:{
		ico:function(icon, hand,action,cfg){
			
			if(Ext.isObject(icon)){
				Factory.btn._(icon.text,icon.hand,icon,action,icon);
			}else {
				(!cfg && Ext.isObject(action)) && (cfg = action);
				
				return Ext.apply(cfg||{},{
					xtype:'button',
					handler:hand,
					icon:URL.icon(icon) + (icon.indexOf('.')===-1? '.png':''),
					action:action
				});
			}
			
		},
		_:function(text,hand,action,cfg){
			if (!Ext.isString(action) && !cfg){// cfg moze być zamiast action (id/name)
				cfg = action;
				action = null;
			}
			var btn = {
				xtype:'button',
				text:text,
				handler:hand,
				action:action
			}
			return cfg ? Ext.apply(btn,cfg) : btn; 
		},
		edit:function(newRecord,what,firstCol,processRecord,cfg){// TODO poukładać
			if(Ext.isString(newRecord)){
				newRecord = Ext.create('TS.model.'+newRecord);
			}
			
			var icon = null;
			if(what && (what.indexOf('#')>-1)){// TODO przemysle ponownie bo to jakis kwas!
				var dx = what.split('#'), what = dx[0], icon = dx[1]; 
			}
			
			var btn = {
				xtype:'button',
				scale:icon? 'small':'large',
				icon:icon? URL.icon(icon) : null,
				text:icon ? null : 'Dodaj' + (what?'<br/>'+what:''),
				handler:function(){
					var me = this;
					!Ext.isObject(cfg) && (cfg = {});
					
					if(cfg.validate && !cfg.validate())return;
					
					if(cfg.confirmCancel){
						me.setText('Anuluj');
					}
					
					var g = this.up('grid'),
						s = g.getStore(),
						p = g.getPlugin('edit')
						t = what ? 'typu '+what : 'tego typu';
					
					if( cfg.confirmCancel && !!Util.search(s.data.items,'phantom',true)){
						Factory.confirm(0,'Czy na pewno chcesz anulować operację?',function(){
							s.load();
							Util.btn('save_status','historystatusgrid').disable();
							me.setText(me.initialConfig.text);
						})	
						return;
					} else {
						if(!Util.valid(
							!!Util.search(s.data.items,'phantom',true),
							'Aktualnie dodajesz obiekt '+t+'. Zapisz wpis lub anuluj zmiany by dodać kolejny.'
						)) return;
					}
					
					newRecord.reject();
					
					processRecord && processRecord(newRecord); 
					
				    p.completeEdit();
				    s.insert(0,[newRecord]);
				    g.getView().refresh();
				    g.getSelectionModel().select(0);
				    p.startEditByPosition({row: 0, column: firstCol || 1});
				}
			}
			Ext.apply(btn,cfg);
			return btn;
		},
		save:function(cb,icon){
			return {
				xtype:'button',
				icon:icon || null,
				handler:Util.f.save,
				text:'Zapisz',
				style:'margin-top:7px;',
				callback:cb||Ext.emptyfn
			}
		}
	},
	rowClass:{
		isNew:function(record, rowIndex, rp, ds){
	        if(record.phantom)return 'pink-row';
	    }
	}
});
window.Factory = Ext.create('TS.lib.Factory');